#include "serialsocket.h"
#include "ui_serialsocket.h"

SerialSocket::SerialSocket(QWidget *parent) :
    QWidget(parent),type(NoType),
    ui(new Ui::SerialSocket)
{
    ui->setupUi(this);
    connect(ui->pushButtonLink,SIGNAL(clicked(bool)),this,SLOT(ConfigSocket()));
    connect(ui->comboBoxBaud,SIGNAL(currentIndexChanged(int)),this,SLOT(serialBaud()));
    connect(ui->pushButtonScan,SIGNAL(clicked(bool)),this,SLOT(serialScan()));
    connect(ui->pushButtonOpen,SIGNAL(clicked(bool)),this,SLOT(serialOpen()));
}

SerialSocket::~SerialSocket()
{
    delete ui;
}

void SerialSocket::ConfigSocket(){
    if(type==Serial)return;
    if(!isValic){
        socketType=ui->comboBoxType->currentIndex();
        switch(socketType){
        case 0://tcpServer
            tcpServer = new QTcpServer;
            tcpSocket = new QTcpSocket;
            ui->lineEditIP->setEnabled(false);
            ipSrcPort = ui->lineEditPort->text().toInt();
            isValic=tcpServer->listen(QHostAddress::Any,ipSrcPort);
            if(!isValic){
                QMessageBox::information(this,"error","socket listen error!","ok");
                delete tcpServer;
                delete tcpSocket;
            }
            else connect(tcpServer,SIGNAL(newConnection()),this,SLOT(NewConnect()));
            break;
        case 1://tcpClient
            tcpSocket = new QTcpSocket;
            ipDetPort = ui->lineEditPort->text().toInt();
            ipAddr = QHostAddress(ui->lineEditIP->text());
            tcpSocket->connectToHost(ipAddr, ipDetPort);
            if(!tcpSocket->waitForConnected(1000)){
                QMessageBox::information(this,"error","connection failed!","ok");
                delete tcpSocket;
            }
            else{
                isValic=true;
                connect(tcpSocket, SIGNAL(readyRead()),this, SLOT(RecvPackets()));
                connect(tcpSocket, SIGNAL(disconnected()),this, SLOT(DisConnect()));
            }
            break;
        case 2://updServer
            udpSocket = new QUdpSocket;
            ui->lineEditIP->setEnabled(false);
            ipSrcPort = ui->lineEditPort->text().toInt();
            isValic = udpSocket->bind(ipSrcPort);
            if(!isValic){
                QMessageBox::information(this,"error","socket bind error!","ok");
                delete udpSocket;
            }
            else connect(udpSocket, SIGNAL(readyRead()),this, SLOT(RecvPackets()));
            break;
        case 3://udpClient
            udpSocket = new QUdpSocket;
            ipDetPort = ui->lineEditPort->text().toInt();
            ipAddr = QHostAddress(ui->lineEditIP->text());
            isValic = true;
            break;
        }
    }
    else{
        switch(socketType){
        case 0://tcpServer
            ui->lineEditIP->setEnabled(true);
            tcpSocket->disconnected();
            tcpServer->close();
            disconnect(tcpSocket);
            delete tcpSocket;
            delete tcpServer;
            break;
        case 1://tcpClient
            tcpSocket->disconnectFromHost();
            disconnect(tcpSocket);
            delete tcpSocket;
            break;
        case 2://updServer
            ui->lineEditIP->setEnabled(true);
            disconnect(udpSocket);
            delete udpSocket;
            break;
        case 3://udpClient
            disconnect(udpSocket);
            delete udpSocket;
            break;
        }
        isValic = false;
    }
    if(isValic){
        ui->pushButtonLink->setText("unlink");
        ui->comboBoxType->setEnabled(false);
        type = Socket;
    }
    else{
        ui->pushButtonLink->setText("link");
        ui->comboBoxType->setEnabled(true);
        type = NoType;
    }
}

void SerialSocket::NewConnect(void){
    tcpSocket = tcpServer->nextPendingConnection();
    connect(tcpSocket, SIGNAL(readyRead()),this, SLOT(RecvPackets()));
}

void SerialSocket::DisConnect(void){
    isValic = false;
    ui->pushButtonLink->setText("link");
    ui->comboBoxType->setEnabled(true);
}

void SerialSocket::RecvPackets(){
    dataRx.clear();
    if(type==Socket){
        switch(socketType){
        case 0://tcpServer
            dataRx=tcpSocket->readAll();
            break;
        case 1://tcpClient
            dataRx=tcpSocket->readAll();
            break;
        case 2://updServer
            dataRx.resize(udpSocket->pendingDatagramSize());
            udpSocket->readDatagram(dataRx.data(), dataRx.size(),&ipAddr,&ipDetPort);
            break;
        case 3://udpClient
            dataRx.resize(udpSocket->pendingDatagramSize());
            udpSocket->readDatagram(dataRx.data(), dataRx.size(),NULL,NULL);
            break;
        }
    }
    else if(type==Serial){
        dataRx = serialport->readAll();
    }
    emit ReadyRecv(dataRx);
}

void SerialSocket::SendPackets(QByteArray &data){
    if(type==Socket){
        switch(socketType){
        case 0://tcpServer
            tcpSocket->write(data);
            break;
        case 1://tcpClient
            tcpSocket->write(data);
            break;
        case 2://updServer
            udpSocket->writeDatagram(data, data.size(), ipAddr, ipDetPort);
            break;
        case 3://udpClient
            udpSocket->writeDatagram(data, data.size(), ipAddr, ipDetPort);
            if(udpSocket->localPort()!=ipSrcPort){
                ipSrcPort = udpSocket->localPort();
                connect(udpSocket, SIGNAL(readyRead()),this, SLOT(RecvPackets()));
            }
            break;
        }
    }
    else if(type==Serial){
        serialport->write(data);
    }
}

void SerialSocket::serialScan()
{
    ui->comboBoxPort->clear();
    foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
    {
        ui->comboBoxPort->addItem(info.portName());
    }
}

void SerialSocket::serialBaud()
{
    if(isValic)serialport->setBaudRate(ui->comboBoxBaud->currentText().toInt());
}

void SerialSocket::serialOpen()
{
    if(type==Socket)return;
    if(!isValic)
    {
        QString portname = ui->comboBoxPort->currentText();
        QSerialPortInfo portInfo(portname);
        if(portInfo.isNull())
        {
            QMessageBox::information(this,"error","serial isn't existed!","ok");
            return;
        }
        if(portInfo.isBusy())
        {
            QMessageBox::information(this,"error","serial is already openned!","ok");
            return;
        }
        serialport = new QSerialPort;
        serialport->setPortName(portname);
        serialport->open(QIODevice::ReadWrite);
        serialport->setBaudRate(ui->comboBoxBaud->currentText().toInt());
        serialport->setDataBits(QSerialPort::Data8);
        serialport->setParity(QSerialPort::NoParity);
        serialport->setStopBits(QSerialPort::OneStop);
        serialport->setFlowControl(QSerialPort::NoFlowControl);
        connect(serialport,SIGNAL(readyRead()),this,SLOT(serialRead()));
        connect(serialport,SIGNAL(error(QSerialPort::SerialPortError)),this,SLOT(serialError()));
        ui->pushButtonOpen->setText("close");
        ui->comboBoxPort->setEnabled(false);
        type = Serial;
        isValic = true;
    }
    else
    {
        serialport->close();
        delete serialport;
        ui->pushButtonOpen->setText("open");
        ui->comboBoxPort->setEnabled(true);
        type = NoType;
        isValic = false;
    }
}

void SerialSocket::serialError()
{
    QMessageBox::information(this,"error",serialport->errorString(),"ok");
    ui->pushButtonOpen->setText("open");
    ui->comboBoxPort->setEnabled(true);
    isValic = false;
    ui->comboBoxPort->clear();
    foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
    {
        ui->comboBoxPort->addItem(info.portName());
    }
}
